// -*-mode:c++; coding:utf-8-*-
#ifndef _XBASE_SSTABLE_BLOCK_CACHE_BASE_HPP_
#define _XBASE_SSTABLE_BLOCK_CACHE_BASE_HPP_

#include <string>

#include <kv.hpp>

namespace xbase
{

	struct cache_key
	{
		typedef uint32_t file_id_type;
		typedef uint32_t block_index_type;

		file_id_type m_file_id;
		block_index_type m_block_index;

		cache_key()
			: m_file_id(file_id_type(-1))
			, m_block_index(block_index_type(-1)) {}

		cache_key(file_id_type file_id, block_index_type index)
			: m_file_id(file_id)
			, m_block_index(index) {}

		bool operator==(const cache_key &other) const {
			return (m_file_id == other.m_file_id)
				&& (m_block_index == other.m_block_index);
		}

		std::size_t hash() const {
			return (static_cast<std::size_t>(m_file_id) << (sizeof(std::size_t) * 8 / 2))
				^ (static_cast<std::size_t>(m_block_index));
		}

		std::string to_string() const;
	};
	
	struct block_entry
	{
		block_entry(){}
		
		block_entry(const key_wrapper *key,
			    const value_wrapper *value)
			: m_key(key)
			, m_value(value) {}
		
		const key_wrapper* m_key;
		const value_wrapper* m_value;
	};

	struct block_entry_less_than
		: public key_less_than
	{
		bool operator()(const block_entry &entry1,
				const block_entry &entry2) const {
			return this->key_less_than::operator()(entry1.m_key, entry2.m_key);
		}
		bool operator()(const block_entry &entry,
				const key_wrapper *key) const {
			return this->key_less_than::operator()(entry.m_key, key);
		}
		bool operator()(const key_wrapper *key,
				const block_entry &entry) const {
			return this->key_less_than::operator()(key, entry.m_key);
		}
	};

	typedef std::vector<block_entry> block_index_type;

	struct cache_value
	{
		std::size_t m_ref_count;
		char *m_block_data;
		std::size_t m_block_size;
		std::size_t m_alloc_size; // 有这个字段，可以更好的使
					  // sstable_block_buffer模拟
					  // simple_buffer<>的行为
		block_index_type m_block_index;

		cache_value()
			: m_ref_count(0)
			, m_block_data(NULL)
			, m_block_size(0)
			, m_alloc_size(0) {}

		std::size_t ref_count() const {
			return m_ref_count;
		}

		void reset_ref_count(std::size_t value) {
			m_ref_count = value;
		}

		void inc_ref_count() {
			++ m_ref_count;
		}

		void dec_ref_count() {
			-- m_ref_count;
		}

		std::size_t size() const {
			return m_block_size;
		}

		boost::asio::mutable_buffer data() {
			return boost::asio::mutable_buffer(m_block_data,
							   m_block_size);
		}
	
		boost::asio::const_buffer data() const {
			return boost::asio::const_buffer(m_block_data,
							 m_block_size);
		}

		bool build_index();

		std::string to_string() const;
	};

	struct cache_node
	{
		cache_key m_key;
		cache_value m_value;

		std::string to_string() const;
	};

} // namespace xbase

#endif	// _XBASE_SSTABLE_BLOCK_CACHE_BASE_HPP_
